# Animal类
class Animal:
    # 类属性，类属性时类体中所有方法外的变量，称之为类属性或者类变量
    Animal = 'animal1'

    # 构造函数 创建类的时候就会被调用
    def __init__(self):
        # 实例属性，类体中方法内并且命名格式为self.变量名=变量值，称之为实例变量
        self.get_name = "animal2"
        print("实例化类时被调用")

    def name(self):
        print("animal3")

    # 类方法，必须要有self
    def set_name(self, name):
        self.get_name = name  # 在类方法中直接可以引用实例变量
        # 局部变量 类体中方法内 以 变量名 = 变量值 的方式称之为局部变量
        set_name = self.get_name
        set_name1 = name
        print("name:{0},self.get_name:{1},set_name:{2},set_name1:{3}".format(name, self.get_name, set_name, set_name1))

    # 析构函数
    def __del__(self):
        print("销毁时被调用")


# Cat 继承Animal
class Cat(Animal):
    # 多态性，在新类里重新定义一个和类中一样的方法
    def name(self):
        print("Cat Animal")

    # 静态方法，没有self
    @staticmethod
    def Cat_name():
        print("my name is cat")


Cat.Cat_name()  # 直接调用静态方法不用实例化都可以调用
cat = Cat()  # 实例化
cat.name()  # 调用方法，这个时候，由于多态性调用的是Cat下面的方法
cat.set_name("小猫咪")  # 调用父类中的方法，实现继承方法

"""
类的使用：
在使用类之前需要实例化类，类实例化之后成为常见的对象，创建对象和创建变量类似，需要先声明对象是哪个类，
同时指明变量名称。
class new_class:
    pass
NEW_CLASS=new_class()
print(type(NEW_CLASS))
print(NEW_CLASS)

"""

"""
类的构造方法
很多类都可能需要有特定的初始化状态，所以一个类可以定义一个特殊的方法，叫做够构造函数，在python中构造函数就是类的__init__方法，
这个和c++的构造的命名有些不同。注意构造函数中的第一个参数是 self，不能遗漏，构造方法返回值必须None

"""


class new_class:
    def __init__(self):
        print("我是类中的构造方法")

    pass


NEW_CLASS = new_class()

"""
在c++中我们对成员变量的声明有 public、private、protected 在引用类的时候对类中成员变量的访问会受到限制，
python中私有属性中只要在定义属性的时候使用两条下划线作为开头，解释器就会认为这个属性是私有属性，外部不能谁便访问这个属性。
我们虽然可以给私有属性赋值，但是不能直接使用类中的私有属性，私有方法和私有属性一样只能在类内被调用
"""


class new_class:
    def __init__(self, name):
        self.__name = name
        self.age = 13

    def __set_name(self, sex):
        self.get_sex = sex
        print("get_sex:{0}".format(self.get_sex))


NEW_CLASS = new_class("天")
# 调用其中的私有属性就会报错
# print(NEW_CLASS.__name)
# 调用其中的私有方法就会报错
# NEW_CLASS.__set_name("男")


"""
继承和多态
面向对象编程三大特性：封装性，继承性，多态性
"""
"""
继承：指在原有的基础上拓展新的属性和方法，原来的类成为父类，后来的类称为子类，python支持多继承
class new_class(Baseclass1, Baseclass2):
    语法块
	......
要定义从哪个父类继承，只需要在定义子类的名字后面的括号类填入父类的名字，多重继承的时候只需要使用“，”来
隔开就行。继承的时候需要记住两点：
1）在继承中如果子类定义了构造函数，则父类的构造方法__init__不会被自动调用，需要在子类的构造方法中专门调用
2）子类不能继承父类中的私有方法，也不能调用父类的私有方法

"""


class class_one:
    def __init__(self, name):
        self.name = name

    def class_one_function_name(self):
        print("class_one_function_name input name", self.name)

    def __private_class(self):
        print("class_one 私有类{0}".format(self.name))


class class_two:
    def __init__(self, name):
        self.name = name

    def class_two_function_name(self):
        print("class_two_function_name input name", self.name)

    def __private_class(self):
        print("class_two 私有类{0}".format(self.name))


# 单继承
class new_class_one(class_one):
    pass


# 多继承
class new_class_two(class_one, class_two):
    pass


# 继承中子类的构造函数
class new_class_three(class_one):
    def __init__(self):
        # 在子类的构造函数类调用父类的构造函数
        super(new_class_three, self).__init__("苏爱仁")


# 实例化对象
print("----------------NEW_CLASS_ONE----------------")
New_class_one = new_class_one("苏毅城")
New_class_one.class_one_function_name()
print("---------------------------------------------")
# 不能直接调用父类中的私有方法
# New_class_one.__private_class()
print("----------------NEW_CLASS_TWO----------------")
New_class_two = new_class_two("苏天")
# 新类的多继承
New_class_two.class_one_function_name()
New_class_two.class_two_function_name()
print("---------------------------------------------")
print("----------------NEW_CLASS_THREE--------------")
New_class_three = new_class_three()
New_class_three.class_one_function_name()
print("---------------------------------------------")

"""
多态：
继承可以帮助我们重复使用代码，但是有时候子类的行为不一定和父类一样。下面就是我们在调用同一个方法时候我们想要输出不同的结果的时候却是输出相同的结果
"""


class Animal:
    def name(self):
        print("Animal")


class Cat(Animal):
    pass


class Dog(Animal):
    pass


Animal_Cat = Cat()
Animal_Cat.name()
Animal_Dog = Dog()
Animal_Dog.name()


# 在python 中的多态和c++的虚函数一样表达意思，python中子类的方法会覆盖掉的父类中相同名字的方法
class Animal:
    def name(self):
        print("Animal")


class Cat(Animal):
    def name(self):
        print("Cat")

    pass


class Dog(Animal):
    def name(self):
        print("Dog")

    pass


Animal_Cat = Cat()
Animal_Cat.name()
Animal_Dog = Dog()
Animal_Dog.name()
